home *** CD-ROM | disk | FTP | other *** search
-
- Multiple csg objects:
- The patches to csg.c and csg.h make it possible to have more than
- two objects in a CSG object. This is a little hack.
-
- ======================= cut here ========================
- *** csg.h.orig Wed Jun 17 18:06:22 1992
- --- csg.h Wed Jun 17 18:08:38 1992
- ***************
- *** 34,40 ****
-
- typedef struct Csg {
- char operator; /* Union, Intersect, or Difference */
- ! struct Geom *obj1, *obj2;
- int (*intmeth)(); /* Intersection method. */
- Float bounds[2][3];
- } Csg;
- --- 34,41 ----
-
- typedef struct Csg {
- char operator; /* Union, Intersect, or Difference */
- ! struct Geom *list; /* Csg objects */
- ! int nobjs; /* Number of objects in the list */
- int (*intmeth)(); /* Intersection method. */
- Float bounds[2][3];
- } Csg;
- *** csg.c.orig Wed Jun 17 17:46:54 1992
- --- csg.c Wed Jun 17 18:02:01 1992
- ***************
- *** 40,46 ****
-
- csg = (Csg *)share_malloc(sizeof(Csg));
- csg->operator = op;
- ! csg->obj1 = csg->obj2 = (Geom *)NULL;
-
-
- switch(op) {
- --- 40,46 ----
-
- csg = (Csg *)share_malloc(sizeof(Csg));
- csg->operator = op;
- ! csg->list = (Geom *)NULL;
-
-
- switch(op) {
- ***************
- *** 82,123 ****
- return csgName;
- }
-
- - csg_intersect_objs(csg, ray, hit1, hit2, mindist, dist1, dist2)
- - Csg *csg;
- - Ray *ray;
- - HitList *hit1, *hit2;
- - Float mindist, *dist1, *dist2;
- - {
- - int operator;
- -
- - hit1->nodes = 0;
- - hit2->nodes = 0;
- - *dist1 = FAR_AWAY;
- - *dist2 = FAR_AWAY;
- - operator = csg->operator;
- -
- - if (!intersect(csg->obj1, ray, hit1, mindist, dist1) &&
- - ((operator == CSG_INTERSECT) || (operator == CSG_DIFFERENCE))) {
- - /*
- - * Intersection and Difference cases: if you miss the first
- - * object, you missed the whole thing.
- - */
- - return FALSE;
- - }
- -
- - if (!intersect(csg->obj2, ray, hit2, mindist, dist2) &&
- - ((operator == CSG_INTERSECT) ||
- - (hit1->nodes == 0) && (operator == CSG_UNION))) {
- - /*
- - * Intersect case: if you miss either object, you miss whole
- - * Union case: if you miss both object, you miss whole
- - */
- - return FALSE;
- - }
- -
- - return TRUE;
- - }
- -
- int
- csg_enter_obj(hitp)
- HitList *hitp;
- --- 82,87 ----
- ***************
- *** 130,143 ****
- }
-
- static int
- ! CsgUnionInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- Ray *ray;
- HitList *hit1p, *hit2p, **hitclose;
- Float dist1, dist2, *distclose;
- {
- ! Float distnext;
- HitList hitnext, *hittmp;
-
- while (TRUE) {
- if (hit2p->nodes == 0 ||
- csg_enter_obj(hit2p)) {
- --- 94,120 ----
- }
-
- static int
- ! CsgUnionInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- ! Csg *csg;
- Ray *ray;
- HitList *hit1p, *hit2p, **hitclose;
- Float dist1, dist2, *distclose;
- {
- ! Float disttmp, distnext;
- HitList hitnext, *hittmp;
- + int sect, fl = 0;
-
- + if (dist1 > dist2) {
- + /* swap so 1 is closest */
- + disttmp = dist2;
- + dist2 = dist1;
- + dist1 = disttmp;
- + hittmp = hit1p;
- + hit1p = hit2p;
- + hit2p = hittmp;
- + fl = 1;
- + }
- +
- while (TRUE) {
- if (hit2p->nodes == 0 ||
- csg_enter_obj(hit2p)) {
- ***************
- *** 149,156 ****
- } else {
- distnext = FAR_AWAY;
- hitnext.nodes = 0;
- ! if (!intersect(hit1p->data[hit1p->nodes-1].obj,
- ! ray, &hitnext, dist2+EPSILON, &distnext)) {
- /*
- * None of obj1 beyond, return hit2 (leaving)
- */
- --- 126,138 ----
- } else {
- distnext = FAR_AWAY;
- hitnext.nodes = 0;
- ! if (fl || csg->nobjs == 1)
- ! sect = intersect(hit1p->data[hit1p->nodes-1].obj,
- ! ray, &hitnext, dist2+EPSILON, &distnext);
- ! else
- ! sect = CsgIntersect(csg,
- ! ray, &hitnext, dist2+EPSILON, &distnext);
- ! if (!sect) {
- /*
- * None of obj1 beyond, return hit2 (leaving)
- */
- ***************
- *** 169,174 ****
- --- 151,157 ----
- dist1 = dist2;
- CsgHitlistCopy(&hitnext, hit2p);
- dist2 = distnext;
- + fl ^= 1;
- /* and continue */
- }
- }
- ***************
- *** 176,189 ****
- }
-
- static int
- ! CsgIntersectInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- Ray *ray;
- HitList *hit1p, *hit2p, **hitclose;
- Float dist1, dist2, *distclose;
- {
- HitList *hittmp, hitnext;
- ! Float distnext;
-
- while (TRUE) {
- if (!csg_enter_obj(hit2p)) {
- /* Ray is leaving obj2 */
- --- 159,185 ----
- }
-
- static int
- ! CsgIntersectInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- ! Csg *csg;
- Ray *ray;
- HitList *hit1p, *hit2p, **hitclose;
- Float dist1, dist2, *distclose;
- {
- HitList *hittmp, hitnext;
- ! Float disttmp, distnext;
- ! int sect, fl = 0;
-
- + if (dist1 > dist2) {
- + /* swap so 1 is closest */
- + disttmp = dist2;
- + dist2 = dist1;
- + dist1 = disttmp;
- + hittmp = hit1p;
- + hit1p = hit2p;
- + hit2p = hittmp;
- + fl = 1;
- + }
- +
- while (TRUE) {
- if (!csg_enter_obj(hit2p)) {
- /* Ray is leaving obj2 */
- ***************
- *** 195,202 ****
- } else {
- distnext = FAR_AWAY;
- hitnext.nodes = 0;
- ! if (!intersect(hit1p->data[hit1p->nodes-1].obj,
- ! ray, &hitnext, dist2+EPSILON, &distnext)) {
- /*
- * None of obj1 beyond, so return miss
- */
- --- 191,203 ----
- } else {
- distnext = FAR_AWAY;
- hitnext.nodes = 0;
- ! if (fl || csg->nobjs == 1)
- ! sect = intersect(hit1p->data[hit1p->nodes-1].obj,
- ! ray, &hitnext, dist2+EPSILON, &distnext);
- ! else
- ! sect = CsgIntersect(csg,
- ! ray, &hitnext, dist2+EPSILON, &distnext);
- ! if (!sect) {
- /*
- * None of obj1 beyond, so return miss
- */
- ***************
- *** 213,218 ****
- --- 214,220 ----
- dist1 = dist2;
- CsgHitlistCopy(&hitnext, hit2p);
- dist2 = distnext;
- + fl ^= 1;
- /* and continue */
- }
- }
- ***************
- *** 220,226 ****
- }
-
- static int
- ! CsgDifferenceInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- Ray *ray;
- HitList *hit1p, *hit2p, **hitclose;
- Float dist1, dist2, *distclose;
- --- 222,229 ----
- }
-
- static int
- ! CsgDifferenceInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- ! Csg *csg;
- Ray *ray;
- HitList *hit1p, *hit2p, **hitclose;
- Float dist1, dist2, *distclose;
- ***************
- *** 227,232 ****
- --- 230,236 ----
- {
- Float distnext;
- HitList hitnext;
- + int sect;
-
- while (TRUE) {
- if (dist1 < dist2) {
- ***************
- *** 240,247 ****
- } else {
- distnext = FAR_AWAY;
- hitnext.nodes = 0;
- ! if (!intersect(hit1p->data[hit1p->nodes-1].obj,
- ! ray, &hitnext, dist2+EPSILON, &distnext)) {
- /*
- * None of obj1 beyond, so
- * return miss
- --- 244,256 ----
- } else {
- distnext = FAR_AWAY;
- hitnext.nodes = 0;
- ! if (csg->nobjs == 1)
- ! sect = intersect(hit1p->data[hit1p->nodes-1].obj,
- ! ray, &hitnext, dist2+EPSILON, &distnext);
- ! else
- ! sect = CsgIntersect(csg,
- ! ray, &hitnext, dist2+EPSILON, &distnext);
- ! if (!sect) {
- /*
- * None of obj1 beyond, so
- * return miss
- ***************
- *** 298,341 ****
- HitList *hitlist;
- Float mindist, *maxdist;
- {
- ! Float dist1, dist2, disttmp, distclose;
- ! HitList hit1, hit2, *hit1p, *hit2p, *hitclose;
-
- ! hit1p = &hit1;
- ! hit2p = &hit2;
- ! if (!csg_intersect_objs(csg, ray, hit1p, hit2p, mindist,
- ! &dist1, &dist2)) {
- ! /* missed the csg object */
- return FALSE;
- }
-
- ! if ((dist1 > dist2) &&
- ! (csg->operator == CSG_UNION || csg->operator == CSG_INTERSECT)) {
- ! /* swap so 1 is closest (except in difference case) */
- ! disttmp = dist2;
- ! dist2 = dist1;
- ! dist1 = disttmp;
- ! hit1p = &hit2;
- ! hit2p = &hit1;
- ! }
-
- ! /*
- ! * Call appropriate intersection method. If FALSE is return,
- ! * no hit of any kind was found.
- ! */
- ! if (!(*csg->intmeth)(ray, hit1p, hit2p, dist1, dist2,
- ! &hitclose, &distclose))
- ! return FALSE;
-
- ! /*
- ! * At this time, the closest hit is in hitclose and
- ! * distclose.
- ! */
- ! if (distclose < mindist || distclose > *maxdist)
- return FALSE;
-
- ! CsgHitlistCopy(hitclose, hitlist);
- ! *maxdist = distclose;
- return TRUE;
- }
-
- --- 307,384 ----
- HitList *hitlist;
- Float mindist, *maxdist;
- {
- ! Float distcsg, distobj, distclose;
- ! HitList hit1, hit2, *hitclose, *hitcsgp, *hitobjp;
- ! int operator, nobjs;
- ! Geom *obj;
-
- ! operator = csg->operator;
- !
- ! hitcsgp = &hit1;
- ! distcsg = FAR_AWAY;
- ! obj = csg->list;
- ! hitcsgp->nodes = 0;
- ! if (!intersect(obj, ray, hitcsgp, mindist, &distcsg) &&
- ! (operator == CSG_INTERSECT || operator == CSG_DIFFERENCE)) {
- ! /*
- ! * Intersection and Difference cases: if you miss the
- ! * first object, you missed the whole thing.
- ! */
- return FALSE;
- }
-
- ! hitobjp = &hit2;
- ! hitclose = &hit1;
- ! distclose = distcsg;
-
- ! nobjs = csg->nobjs;
- ! csg->nobjs = 0;
-
- ! while(++csg->nobjs < nobjs) {
- ! obj = obj->next;
- ! hitobjp->nodes = 0;
- ! distobj = FAR_AWAY;
- ! if (!intersect(obj, ray, hitobjp, mindist, &distobj)) {
- ! if (operator == CSG_INTERSECT) {
- ! csg->nobjs = nobjs;
- ! return FALSE;
- ! }
- ! if (hitcsgp->nodes == 0)
- ! continue;
- ! }
- !
- !
- ! /*
- ! * Call appropriate intersection method. If FALSE is return,
- ! * no hit of any kind was found.
- ! */
- ! if (!(*csg->intmeth)(csg, ray, hitcsgp, hitobjp, distcsg, distobj,
- ! &hitclose, &distclose) || distclose > *maxdist) {
- ! if (operator != CSG_UNION) {
- ! csg->nobjs = nobjs;
- ! return FALSE;
- ! }
- ! hitcsgp->nodes = 0;
- ! distcsg = FAR_AWAY;
- ! continue;
- ! }
- !
- ! /*
- ! * At this time, the closest hit is in hitclose and
- ! * distclose.
- ! */
- ! distcsg = distclose;
- ! hitcsgp = hitclose;
- ! if (hitcsgp == &hit1)
- ! hitobjp = &hit2;
- ! else
- ! hitobjp = &hit1;
- ! }
- ! if (hitcsgp->nodes == 0 || distcsg < mindist || distcsg > *maxdist)
- return FALSE;
-
- ! CsgHitlistCopy(hitcsgp, hitlist);
- ! *maxdist = distcsg;
- return TRUE;
- }
-
- ***************
- *** 355,387 ****
- Csg *csg;
- Float bounds[2][3];
- {
- ! GeomComputeBounds(csg->obj1);
- ! GeomComputeBounds(csg->obj2);
-
- switch (csg->operator) {
- case CSG_UNION:
- ! bounds[LOW][X] = min(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
- ! bounds[HIGH][X] = max(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
- ! bounds[LOW][Y] = min(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
- ! bounds[HIGH][Y] = max(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
- ! bounds[LOW][Z] = min(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
- ! bounds[HIGH][Z] = max(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
- break;
- case CSG_INTERSECT:
- ! bounds[LOW][X] = max(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
- ! bounds[HIGH][X] = min(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
- ! bounds[LOW][Y] = max(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
- ! bounds[HIGH][Y] = min(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
- ! bounds[LOW][Z] = max(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
- ! bounds[HIGH][Z] = min(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
- break;
- case CSG_DIFFERENCE:
- - bounds[LOW][X] = csg->obj1->bounds[LOW][X];
- - bounds[HIGH][X] = csg->obj1->bounds[HIGH][X];
- - bounds[LOW][Y] = csg->obj1->bounds[LOW][Y];
- - bounds[HIGH][Y] = csg->obj1->bounds[HIGH][Y];
- - bounds[LOW][Z] = csg->obj1->bounds[LOW][Z];
- - bounds[HIGH][Z] = csg->obj1->bounds[HIGH][Z];
- break;
- default:
- RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
- --- 398,438 ----
- Csg *csg;
- Float bounds[2][3];
- {
- ! Geom *obj;
-
- + for (obj = csg->list; obj; obj = obj->next)
- + GeomComputeBounds(obj);
- +
- + obj = csg->list;
- + bounds[LOW][X] = obj->bounds[LOW][X];
- + bounds[HIGH][X] = obj->bounds[HIGH][X];
- + bounds[LOW][Y] = obj->bounds[LOW][Y];
- + bounds[HIGH][Y] = obj->bounds[HIGH][Y];
- + bounds[LOW][Z] = obj->bounds[LOW][Z];
- + bounds[HIGH][Z] = obj->bounds[HIGH][Z];
- +
- switch (csg->operator) {
- case CSG_UNION:
- ! while (obj = obj->next) {
- ! bounds[LOW][X] = min(bounds[LOW][X], obj->bounds[LOW][X]);
- ! bounds[HIGH][X] = max(bounds[HIGH][X], obj->bounds[HIGH][X]);
- ! bounds[LOW][Y] = min(bounds[LOW][Y], obj->bounds[LOW][Y]);
- ! bounds[HIGH][Y] = max(bounds[HIGH][Y], obj->bounds[HIGH][Y]);
- ! bounds[LOW][Z] = min(bounds[LOW][Z], obj->bounds[LOW][Z]);
- ! bounds[HIGH][Z] = max(bounds[HIGH][Z], obj->bounds[HIGH][Z]);
- ! }
- break;
- case CSG_INTERSECT:
- ! while (obj = obj->next) {
- ! bounds[LOW][X] = max(bounds[LOW][X], obj->bounds[LOW][X]);
- ! bounds[HIGH][X] = min(bounds[HIGH][X], obj->bounds[HIGH][X]);
- ! bounds[LOW][Y] = max(bounds[LOW][Y], obj->bounds[LOW][Y]);
- ! bounds[HIGH][Y] = min(bounds[HIGH][Y], obj->bounds[HIGH][Y]);
- ! bounds[LOW][Z] = max(bounds[LOW][Z], obj->bounds[LOW][Z]);
- ! bounds[HIGH][Z] = min(bounds[HIGH][Z], obj->bounds[HIGH][Z]);
- ! }
- break;
- case CSG_DIFFERENCE:
- break;
- default:
- RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
- ***************
- *** 424,454 ****
- Geom *list;
- {
- static int OpenAdvised = FALSE;
- ! /*
- ! * Currently, this only handles two objects.
- ! * Will be fixed in the future.
- ! * No really we promise.
- ! */
- ! if (!list || !list->next) {
- ! RLerror(RL_WARN, "CSG needs at least two objects.\n");
- return 0;
- }
- ! if (list->next->next) {
- ! RLerror(RL_WARN, "Currently, CSG only handles two objects.\n");
- ! return 0;
- }
- /*
- * Things are put into lists backwards....
- */
- ! csg->obj2 = list;
- ! csg->obj1 = list->next;
- ! if ((!csg->obj1->methods->closed || !csg->obj2->methods->closed) &&
- ! !OpenAdvised) {
- ! RLerror(RL_ADVISE,
- ! "Performing CSG with non-closed object(s).\n");
- ! OpenAdvised = TRUE;
- }
- ! return csg->obj1->prims + csg->obj2->prims;
- }
-
- void
- --- 475,517 ----
- Geom *list;
- {
- static int OpenAdvised = FALSE;
- ! Geom *obj, *prev;
- ! int prims = 0;
- ! int nobjs = 0;
- !
- ! if (!list) {
- ! RLerror(RL_WARN, "CSG needs at least one object.\n");
- return 0;
- }
- ! if (!list->next) {
- ! RLerror(RL_WARN, "CSG with only one object.\n");
- }
- + prev = (Geom *)0;
- + for (obj = list; ; obj = obj->next) {
- + if ((!obj->methods->closed) &&
- + !OpenAdvised) {
- + RLerror(RL_ADVISE,
- + "Performing CSG with non-closed object(s).\n");
- + OpenAdvised = TRUE;
- + }
- + prims += obj->prims;
- + nobjs++;
- + if (!obj->next)
- + break;
- + prev = obj;
- + }
- /*
- * Things are put into lists backwards....
- + * To make the Difference methode work, we move the last
- + * element of the list to the head.
- */
- ! csg->list = obj;
- ! if (prev) {
- ! prev->next = 0;
- ! obj->next = list;
- }
- ! csg->nobjs = nobjs;
- ! return prims;
- }
-
- void
-